#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <string>
#include <iostream>

using namespace std;
using namespace testing;

class Foo {
public:
    static int static_func() 
    {
        return 0;
    }

    int public_func();

protected:
    int protected_func()
    {
        return 0;
    }

private:
    int private_func() 
    {
        return 0;
    }
};

class MockFoo : public Foo {
 public:
  MOCK_METHOD(int, static_func, ());
  MOCK_METHOD(int, public_func, ());
  // The following must be in the public section, even though the
  // methods are protected or private in the base class.
  MOCK_METHOD(int, protected_func, ());
  MOCK_METHOD(int, private_func, ());
};

int Foo::public_func()
{
    MockFoo foo;
    EXPECT_CALL(foo, protected_func())
        .WillRepeatedly(Return(2));
    cout << "protected_func return : " << foo.protected_func() << endl;

    EXPECT_CALL(foo, private_func())
        .WillRepeatedly(Return(3));
    cout << "private_func return : " << foo.private_func() << endl;
    return 0;
}

TEST(sample, cpp_class_static_func)
{
    MockFoo foo;
    EXPECT_CALL(foo, static_func())
        .WillRepeatedly(Return(1));

    EXPECT_EQ(1, foo.static_func());
}

TEST(sample, cpp_class_public_func)
{
    MockFoo foo;
    EXPECT_CALL(foo, public_func())
        .WillRepeatedly(Return(2));

    EXPECT_EQ(2, foo.public_func());
}

TEST(sample, cpp_class_protected_func)
{
    MockFoo foo;
    EXPECT_CALL(foo, protected_func())
        .WillRepeatedly(Return(3));

    EXPECT_EQ(3, foo.protected_func());
}

TEST(sample, cpp_class_private_func)
{
    MockFoo foo;
    EXPECT_CALL(foo, private_func())
        .WillRepeatedly(Return(4));

    EXPECT_EQ(4, foo.private_func());
}

int main(int argc, char *argv[])
{
    Foo foo;
    foo.public_func();

    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
